/***************************************************************************\
 * The Mattise Kernel														*
 * Copyright 2007 Matthew Iselin											*
 * Licensed under the GPL													*
 *																			*
 * oscalls.cc																*
 *																			*
 * Calls required by newlib are implemented in this code. Not to be linked	*
 * into the kernel.															*
 *																			*
\***************************************************************************/

// DON'T link us into the kernel (change to #if 1 when compiling with newlib)
#if 1

// includes
#include <sys/stat.h>
#include <sys/types.h>
#include <_ansi.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <reent.h>

// we need to define our own version of errno
#undef errno
extern int errno;

// kills a program, no cleanup at all
void _exit()
{
	asm( "mov $0,%eax\nint $0x80" );
}

// closes a file
int close( int fd )
{
	unsigned int ebx;
	asm( "mov $10,%%eax\nint $0x80" : "=b" (ebx) : "c" (fd) );
	return ebx;
}

// environment variable list
char* env[1] = { 0 };
char** environ = env;

// transfers control to a new process
int execve( char* name, char** argv, char** env )
{
	errno = ENOMEM;
	return -1;
}

// creates a new process
int fork()
{
	errno = EAGAIN;
	return -1;
}

// gets the status of an open file
int fstat( int file, struct stat* st )
{
	st->st_mode = S_IFCHR;
	return 0;
}

// gets the current process id
int getpid()
{
	unsigned int ebx;
	asm( "mov $22,%%eax\nint $0x80" : "=b" (ebx) );
	return ebx;
}

// query whether an output stream is a terminal
int isatty( int fd )
{
	return 1;
}

// sends a signal to a process
int kill( int pid, int sig )
{
	errno = EINVAL;
	return -1;
}

// establishes a new name for an existing file
int link( char* old, char* newf )
{
	errno = EMLINK;
	return -1;
}

// seeks to a position in a file
int lseek( int file, int ptr, int dir )
{
	unsigned int ebx;
	asm( "int $0x80" : "=b" (ebx) : "a" (14), "b" (dir), "c" (file), "d" (ptr) );
	return ebx;
}

// opens a file
int open( const char* name, int flags, ... )
{
	va_list vl;
	va_start(vl,flags);
	int mode = va_arg( vl, int );
	va_end(vl);
	unsigned int ebx;
	asm( "int $0x80" : "=b" (ebx) : "a" (9), "S" ((unsigned int) name), "c" (mode) );
	return ebx;
}

// reads from a file
int read( int fd, char* ptr, int len )
{
	unsigned int ebx;
	asm( "int $0x80" : "=b" (ebx) : "a" (15), "S" ((unsigned int) ptr), "c" (fd), "d" (len) );
	return ebx;
}

caddr_t sbrk( int incr )
{
	// the new end of the memory
	unsigned int newend = 0;
	asm( "int $0x80" : "=b" (newend) : "a" (26), "c" (incr) );
	
	// return it
	return (caddr_t) newend;
}

// gets the status of a file
int _stat( char* file, struct stat* st )
{
	st->st_mode = S_IFCHR;
	return 0;
}

// gets timing information for the current process
int times( struct tms* buf )
{
	return -1;
}

// removes a file directory entry
int unlink( char* name )
{
	errno = ENOENT;
	return -1;
}

// wait for a child process
int wait( int* status )
{
	errno = ECHILD;
	return -1;
}

// writes to a file
int write( int fd, char* ptr, int len )
{
	unsigned int ebx;
	asm( "int $0x80" : "=b" (ebx) : "a" (18), "S" ((unsigned int) ptr), "c" (fd), "d" (len) );
	return ebx;
}

#endif
